package com.hengpeng.itfinoss.service.impl;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;
import com.hengpeng.common.exception.GenericType;
import com.hengpeng.common.persist.QueryParameter;
import com.hengpeng.common.persist.QueryResult;
import com.hengpeng.common.persist.entity.AbstractEntity;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.itfinbase.message.ResponseMessage;
import com.hengpeng.itfinbase.message.TransMessage;
import com.hengpeng.itfinoss.service.RemoteService;
import com.hengpeng.itfinoss.service.ServiceFactory;
import com.hengpeng.itfinoss.util.ConfigUtil;
import com.hengpeng.itfinoss.util.DigestAuthUtils;

/**
 * 远程查询数据接口
 * @author lmm
 * @version 20120528
 */

@Service
public class RemoteServiceImpl implements RemoteService
{
	private final static Log logger = LogFactory.getLog(RemoteServiceImpl.class);

	private static final String DigestAuth_ClientId = "client";

	private static final String DigestAuth_ClientPwd = "client";

	private static final String DigestAuth_Key = "acegi";

	private static final String DigestAuth_RealName = "Contacts Realm via Digest Authentication";

	private static final String RemoteServiceUrl = ConfigUtil.getConfigValue("remote.service.url") + "/RemoteService/";

	@Autowired
	private ServiceFactory serviceFactory;

	@SuppressWarnings("unchecked")
	public <T> T doJsonGenericPostTrans(String transName, final GenericType<T> type, Object parameter,
			Object... pathValue)
	{
		String url = RemoteServiceUrl + transName;
		HttpHeaders requestHeaders = DigestAuthUtils.createAuthHeaders(url, HttpMethod.POST.name(),
				DigestAuth_ClientId, DigestAuth_RealName, DigestAuth_ClientPwd, DigestAuth_Key);

		// 设置JSON转换器
		List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
		converters.add(new MappingJacksonHttpMessageConverter()
		{
			@Override
			protected JavaType getJavaType(Type typeInner, Class<?> clazz)
			{
				return TypeFactory.type(type.getType());
			}
		});
		RestTemplate genericRestTemplate = new RestTemplate();
		genericRestTemplate.setMessageConverters(converters);

		HttpEntity<Object> entity = new HttpEntity<Object>(parameter, requestHeaders);
		return (T) genericRestTemplate.postForEntity(url, entity, type.getType().getClass(), pathValue).getBody();
	}

	public <T> T doPostTrans(String transName, Class<T> returnType, Object parameter, Object... pathValue)
	{
		String url = RemoteServiceUrl + transName;
		HttpEntity<Object> entity = new HttpEntity<Object>(parameter, DigestAuthUtils.createAuthHeaders(url,
				HttpMethod.POST.name(), DigestAuth_ClientId, DigestAuth_RealName, DigestAuth_ClientPwd, DigestAuth_Key));
		return (T) serviceFactory.getRestTemplate().postForEntity(url, entity, returnType, pathValue).getBody();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends AbstractEntity> List<Object> findObject(Class<T> type, DynamicQuery query)
	{
		QueryParameter<T> queryParameters = new QueryParameter<T>();
		queryParameters.setType(type);
		queryParameters.setCustomQuery(query);
		QueryResult<?> doPostTrans = this.doPostTrans("remoteQuery", QueryResult.class, queryParameters);
		return (List<Object>) doPostTrans.getResults();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends AbstractEntity> List<Object[]> findObjectArray(Class<T> type, DynamicQuery query)
	{
		QueryParameter<T> queryParameters = new QueryParameter<T>();
		queryParameters.setType(type);
		queryParameters.setCustomQuery(query);
		QueryResult<?> doPostTrans = this.doPostTrans("remoteQuery", QueryResult.class, queryParameters);
		return (List<Object[]>) doPostTrans.getResults();
	}

	@Override
	public ResponseMessage remoteTrans(TransMessage transMessage)
	{
		Gson gson = new Gson();
		logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,请求参数:{" + gson.toJson(transMessage) + "}");
		ResponseMessage doPostTrans = this.doPostTrans("remoteTrans", ResponseMessage.class, transMessage);
		logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,响应信息:{" + gson.toJson(doPostTrans) + "}");
		return doPostTrans;
	}

	public <T extends ResponseMessage> T remoteTrans(TransMessage transMessage, Class<T> clz)
	{
		return clz.cast(remoteTrans(transMessage));
	}

}
